import json
import time

from decimal import Decimal
from django import http
from django.contrib.auth.mixins import LoginRequiredMixin
from django.core.paginator import Paginator, EmptyPage
from django.db import transaction
from django.shortcuts import render

# Create your views here.
from django.utils import timezone
from django.views import View
from django_redis import get_redis_connection

from apps.goods.models import SKU
from apps.orders.models import OrderInfo, OrderGoods
from apps.users.models import Address
from utils.response_code import RETCODE



class PlaceOrderView(LoginRequiredMixin,View):
    def get(self,requset):
        user = requset.user
        try:
            addresses = Address.objects.filter(
                user = requset.user,
                is_deleted=False
            )
        except Address.DoesNotExist:
            addresses = None
        redis_conn = get_redis_connection('carts')
        redis_carts = redis_conn.hgetall('carts:%s'%user.id)
        redis_selected = redis_conn.smembers('selected:%s'%user.id)
        cart = {}
        for sku_id in redis_carts:
            cart[int(sku_id)] = int(redis_carts[sku_id])
        skus = SKU.objects.filter(id__in = redis_carts)
        total_count = 0
        total_amount = 0

        for sku in skus:
            sku.count = cart[sku.id]
            sku.amount = sku.count * sku.price

            total_count += sku.count
            total_amount += sku.count *sku.price
        context = {
            'addresses':addresses,
            'skus':skus,
            'total_count':total_count,
            'total_amount': total_amount,
            'freight':10,
            'payment_amount':total_amount+10,

        }
        return render(requset,'place_order.html',context=context)

class OrderCommitView(LoginRequiredMixin,View):
    def post(self, request):
        data = json.loads(request.body.decode())
        address_id = data.get('address_id')
        pay_method = data.get('pay_method')
        if not all([address_id, pay_method]):
            return http.JsonResponse({'code': RETCODE.PARAMERR, 'errmsg': '参数不全'})
        try:
            address = Address.objects.get(pk=address_id)
        except Exception:
            return http.JsonResponse({'code': RETCODE.DBERR, 'errmsg': '地址错误'})
        try:
            pay_method = int(pay_method)
        except Exception as e:
            return  http.JsonResponse({'code':RETCODE.DBERR,'errmsg':'支付有误'})
        total_count = 0
        total_amount = Decimal('0')
        freight = Decimal('10')
        if pay_method not in [OrderInfo.PAY_METHODS_ENUM['CASH'], OrderInfo.PAY_METHODS_ENUM['ALIPAY']]:
            return http.JsonResponse({'code': RETCODE.DBERR, 'errmsg': '支付方式错误'})
        user = request.user
        order_id = timezone.localtime().strftime('%Y%m%d%H%M%S') + '%09d' % user.id

        if pay_method == OrderInfo.PAY_METHODS_ENUM['CASH']:
            status = OrderInfo.ORDER_STATUS_ENUM['UNSEND']
        else:
            status = OrderInfo.ORDER_STATUS_ENUM['UNPAID']
        with transaction.atomic():
            save_point=transaction.savepoint()
            order = OrderInfo.objects.create(
                order_id=order_id,
                user=user,
                address=address,
                total_count=total_count,
                total_amount=total_amount,
                freight=freight,
                pay_method=pay_method,
                status=status
            )
            redis_conn = get_redis_connection('carts')
            redis_carts = redis_conn.hgetall('carts:%s'%user.id)
            redis_selected = redis_conn.smembers('selected:%s'%user.id)
            cart = {}
            for sku_id in redis_selected:
                cart[int(sku_id)] = int(redis_carts[sku_id])
            sku_ids = cart.keys()
            for sku_id in sku_ids:
                sku = SKU.objects.get(pk=sku_id)
                count = cart[sku.id]
                if count > sku.stock:
                    transaction.savepoint_rollback(save_point)
                    return http.JsonResponse({'code':RETCODE.DBERR,'errmsg':'库存不足'})
                # sku.stock -= count
                # sku.sales += count
                # sku.save()
                time.sleep(1)
                old_stock = sku.stock
                new_stock = sku.stock - count
                new_sales = sku.sales + count
                rect = SKU.objects.filter(stock=old_stock, pk=sku.id).update(stock=new_stock, sales=new_sales)
                if rect == 0:
                    transaction.savepoint_rollback(save_point)
                    return http.JsonResponse({'code': RETCODE.STOCKERR, 'errmsg': '库存不足'})
                OrderGoods.objects.create(
                    order=order,
                    sku = sku,
                    count = count,
                    price = sku.price,
                )
                order.total_count += count
                order.total_amount += (count * sku.price)
            order.total_amount += order.freight
            order.save()
            transaction.savepoint_commit(save_point)
        return http.JsonResponse({'code':RETCODE.OK,'errmsg':'ok','order_id':order.order_id,'payment_amount':order.total_amount})



class OrderSuccessView(LoginRequiredMixin,View):
    def get(self, request):
        order_id = request.GET.get('order_id')
        payment_amount = request.GET.get('payment_amount')
        pay_method = request.GET.get('pay_method')
        context = {
            'order_id': order_id,
            'payment_amount': payment_amount,
            'pay_method': pay_method
        }
        return render(request, 'order_success.html', context)


class UserOrderInfoView(LoginRequiredMixin,View):
    def get(self, request, page_num):
        user = request.user
        orders = user.orderinfo_set.all().order_by("-create_time")
        for order in orders:
            order.details = []
            order_goods = order.skus.all()
            for order_good in order_goods:
                sku = order_good.sku
                sku.count = order_good.count
                sku.total_amount = sku.price * sku.count
                order.details.append(sku)
        page_num = int(page_num)
        try:
            paginator = Paginator(orders, 5)
            page = paginator.page(page_num)
            total_page = paginator.num_pages
        except EmptyPage:
            return http.HttpResponseNotFound('订单不存在')

        context = {
            "page": page,
            'total_page': total_page,
            'page_num': page_num,
        }
        return render(request, "user_center_order.html", context)























